#include <new>
#include <random>
#include <stdio.h>
#include <stdlib.h>
#include <sys/shm.h>
#include <string.h>
#include "SvrMemBlock.h"

int CSvrMemBlock::m_id = -1;
CSvrMemBlock *CSvrMemBlock::m_smb = nullptr;

CSvrMemBlock::CSvrMemBlock()
{
    m_iLen = 0;
    m_iCur = 0;
    m_pBlock = nullptr;
}

CSvrMemBlock::~CSvrMemBlock()
{
    Destroy();
}

// 把自身的实例放到共享内存块
CSvrMemBlock *CSvrMemBlock::Create(int iLen)
{
    key_t key = 0;
    void *ptr = nullptr;

    if (nullptr != m_smb)
        return m_smb;

    if (0 >= iLen)
        return nullptr;

    std::default_random_engine dre;
    key = ftok(".", dre() % 255 + 1);

    if (-1 == key)
    {
        perror("ftok error");
        return nullptr;
    }

    m_id = shmget(key, iLen, IPC_CREAT | 0666);

    if (-1 == m_id)
    {
        perror("Create Shared Memory Error");
        return nullptr;
    }

    ptr = shmat(m_id, 0, 0);

    if ((void *)-1 == ptr)
    {
        perror("Attach Shared Memory Error");
        return nullptr;
    }

    memset(ptr, 0, iLen);
    m_smb = new (ptr) CSvrMemBlock();

    if (nullptr != m_smb)
    {
        m_smb->m_pBlock = (char *)ptr + sizeof(CSvrMemBlock);
        m_smb->m_iLen = iLen - sizeof(CSvrMemBlock);
    }

    return m_smb;
}

void CSvrMemBlock::Destroy()
{
    if (nullptr != m_smb)
    {
        struct shmid_ds buf;
        shmdt(m_smb);
        shmctl(m_id, IPC_RMID, &buf);
        m_smb = nullptr;
    }
}

void *CSvrMemBlock::Alloc(int iLen)
{
    void *ptr = nullptr;

    if (0 >= iLen)
    {
        printf("CSvrMemBlock::Alloc param error, iLen=%d\n", iLen);
        return nullptr;
    }

    if (m_iCur + iLen > m_iLen)
    {
        printf("CSvrMemBlock::Alloc param error, (m_iCur + iLen > m_iLen)\n");
        return nullptr;
    }

    ptr = (char *)m_pBlock + m_iCur;
    m_iCur += iLen;

    return ptr;
}

void CSvrMemBlock::Free(void *ptr)
{
    // 空函数，实际需调用Destroy回收所有内存
}